TSKaigi 2024
https://gyazo.com/bea1aefcd1bb0f104ed632a6220f7f88
Keynote
npm downloadsは2兆件を超えた
5.4と5.5の機能を紹介
パフォーマンスとスケーリング
DX向上
--isolatedDeclaration
トレードオフがある
利用しているもの
Compiler API
Language Server Protocol
"Hello"は
ExpressionStatement
StringLiteral
になる
root
node
走査(traverse)=各nodeを訪問すること
幅優先探索 / 深さ優先探索
Visitorパターン
工程
1. ソースコードからASTへ変換(Parse)
2. 木の走査をしながらNode変換(Traverse)
3. ASTからソースコードへ変換(Unparse)
コードジェネレーター実装入門
解決してくれる課題と構造
コード生成機は入力された仕様やスキーマに依存する
入力や成果物もその分無数の選択肢が生まれる
ジェネレーターの開発者の母数が少ない
実装方法
Factory Codeを使う
不正な入力値もできる限り推論を行ってコード生成していた
利用しないパラメーターも記述する必要があるため、冗長になるためラッパーが欲しくなる
ASTとPlain Textをハイブリットに書きたい
sourceFileのstatementsを抽出する
実装量
Template Literalだと最小
独自構文になるかどうか
原理的に思い出しやすくなる
ランチセッション
寺本大輝
島津 真人
丹羽 健
書籍通りにはやってない
Repositoryパターンは不要→なぜ?
interface
オブジェクトの変更は関数適用による状態遷移でイミュータブルにする
命令的なものではない
customer.archive()ではなくconst archived = archiveCustomer(customer)
状態の変化が明示的になる
遷移前の状態は引数
遷移後の状態は戻り値
ユースケースはworkflowとして実装
入力値とドメインオブジェクトがドメインイベントに伴い新しい状態に遷移
値オブジェクトはコンストラクタで生成して失敗した場合はResultで返す
例外の場合はResultで受け取りたい
それ以外は従来通りの作り
なぜ関数型スタイルにしたいのか
静的検査で動かさないとわからないことが減る
オブジェクトの変更を「関数適用による状態遷移」にすると型を記述しやすい すべてが明示的になる
値はだいたいResultに入ってるため
複数Resultがあると合成してフラットにする必要があって面倒・・・
海老原 圭吾
Procedureのinput/outputの方をコード生成無しでクライアントに共有
2024-05-11時点でv11 bataが公開中
AppRouter typeでServer側に型導出する
型に関するGraphQLとの比較
ClientがServerに依存していない
ClientがServerに依存
Data Transformer
シリアライズ・デシリアライズを行う
デフォルトはJSON.stringify, JSON.parse
実装者自身で変更可能
plainではないオブジェクトも復元が可能
この表現力次第で柔軟に値や型が使用できる
データ量にたいしてメタ情報分のデータが増える
1/4がメタ情報になる
パフォーマンス影響あり
対策
outputはサイズ重視で実装
inputはデータ量が大きいのでデバッグのしやすさとのトレードオフ 型ガード関数と同じで嘘を付くと型と簡単にズレていく こういうのは型検査で防ぐことはできないのでUTを書く必要がある アダプター
パッケージ単体はサーバーの機能は提供していない
シンプルなスタンドアローンのものもある
旨味
一部だけtRPCにすることもできる
tRPCになう機能を土台となるアプリケーション機能で補える
フォームデータ
ファイルダウンロード
苦味
フォームデータを扱うのはまだexperimental
なぜ採用したのか?
リソース配分を最適化しやすくする
Full TypeScriptでやっていく
Modelは共有しない
サーバーサイドとクライアントとでアクセスできるものが違う
サーバーサイドでの型の複雑さがクライアントサイドに伝播する
Zodで複雑なデータ構造を定義するために工夫すると生成される型がより複雑になる リポジトリ構成
サーバーのパッケージをクライアントから参照できるようにする
リアルタイムで型が共有されるようになる
workspace沼にはまりやすくあまり活用できてない
サーバーの定義を買えるとその場でクライアント側で型エラーになる
株式会社LIXIL Marketing DevOps. System Dev. & Ope. Digital / アプリケーションエキスパート 親和性とは?
型付け+論理構成=親和性
response.json()がanyなので渡ってくるものは祈ることになる
外部I/Oにおける片付けが不十分だと静的型付けの恩恵を得られない
APIに型をつけるとは?
仕様が定まってない場合はゆるふわになりがちなので定義していく
実装言語の方を自動で生成
手書きするとミスが発生する
生成された型で実装
Client Preset
スキーマからだとすべての型情報をもってしまうので、undefinedになる可能性がある TypedDocumentNode
クライアントに食わせると型が付く
Apollo Client
urql
graphql-request
Fragment Colocation
すべての末端コンポーネントまでトップレベルがクエリが知っている必要がある設計の歪を解消する
Fragment Masking
自身で定義したfragmentの型をほかで使えないようにする
useFragment
第2引数のオブジェクトを返すだけの関数
TypeScript Resolvers
Server Presetは癖が強め
Field Resolverを設定する
mappersでResolverの型を設定して使用する
Prettier Creator: James Long
JSXではなくhyperapp記法でReactを書いていた人 Prettier co-creator: Vjeux
課題点
使い勝手の悪い点
単体で使う分は楽
設定は不要なので
衝突する場合にルールを変更する必要がある
esling-plugin系を組み合わせてやっていた
実行速度が遅い
これはそこまで問題ない
行数が膨大なのは若干カクつく
こういうのは遅い
deno lintとdeno fmtは設定無しで実行できる
現代のフロントエンドツール設定がめんどい・しんどいのでそれを統一したい
npm i -D @biomejs/biome
npx @biomejs/biome init
アルゴリズム
パフォーマンス(単一)
改善するための難易度は高い
パフォーマンス(複数)
劇的に改善はできそう
早くしようとしてなかっただけ
パフォーマンス改善の余地あり
10倍早くできそう(現在改善中)
まだ足りない
リンターとのインテグレーション
そもそもBiomeはLinterを持ってる
どっちも面倒
独自のESLint使いこなしているのはよりしんどい
サポート言語
パーサーが各言語で使える
依存をさせたくないため
プラグイン
記述された言語
最終的にどういう形で配布されるかの違いもある